Imports System.Text
Imports System.Globalization

Namespace FTP
    ''' <summary>
    ''' The MLSx perm options as defined by RFC 3659.
    ''' </summary>
    <Flags> _
    Public Enum MlsxPerm
        ''' <summary>
        ''' No permissions specified.
        ''' </summary>
        None = &H0
        ''' <summary>
        ''' Indicates the file can be appended to.
        ''' </summary>
        ''' <remarks>
        ''' The "a" permission applies to objects of type=file, and indicates
        ''' that the APPE (append) command may be applied to the file named.
        ''' </remarks>
        CanAppendFile = &H1
        ''' <summary>
        ''' Indicates the directory allow files to be created.
        ''' </summary>
        ''' <remarks>
        ''' The "c" permission applies to objects of type=dir (and type=pdir,
        ''' type=cdir).  It indicates that files may be created in the directory
        ''' named.  That is, that a STOU command is likely to succeed, and that
        ''' STOR and APPE commands might succeed if the file named did not
        ''' previously exist, but is to be created in the directory object that
        ''' has the "c" permission.  It also indicates that the RNTO command is
        ''' likely to succeed for names in the directory.
        ''' </remarks>
        CanCreateFile = &H2
        ''' <summary>
        ''' Indicates the directory or file can be deleted.
        ''' </summary>
        ''' <remarks>
        ''' The "d" permission applies to all types.  It indicates that the
        ''' object named may be deleted, that is, that the RMD command may be
        ''' applied to it if it is a directory, and otherwise that the DELE
        ''' command may be applied to it.
        ''' </remarks>
        CanDeleteFile = &H4
        ''' <summary>
        ''' Indicates the change directory command can be executed sucessfully.
        ''' </summary>
        ''' <remarks>
        ''' The "e" permission applies to the directory types.  When set on an
        ''' object of type=dir, type=cdir, or type=pdir it indicates that a CWD
        ''' command naming the object should succeed, and the user should be able
        ''' to enter the directory named.  For type=pdir it also indicates that
        ''' the CDUP command may succeed (if this particular pathname is the one
        ''' to which a CDUP would apply.) 
        ''' </remarks>
        CanChangeDirectory = &H8
        ''' <summary>
        ''' Indicates the directory for file can be renamed.
        ''' </summary>
        ''' <remarks>
        ''' The "f" permission for objects indicates that the object named may be
        ''' renamed - that is, may be the object of an RNFR command.
        ''' </remarks>
        CanRename = &H10
        ''' <summary>
        ''' Indicates the files for the directory can be listed.
        ''' </summary>
        ''' <remarks>
        ''' The "l" permission applies to the directory file types, and indicates
        ''' that the listing commands, LIST, NLST, and MLSD may be applied to the
        ''' directory in question.
        ''' </remarks>
        CanListFiles = &H20
        ''' <summary>
        ''' Indicates directories in this directory may be created.
        ''' </summary>
        ''' <remarks>
        ''' The "m" permission applies to directory types, and indicates that the
        ''' MKD command may be used to create a new directory within the
        ''' directory under consideration.
        ''' </remarks>
        CanCreateDirectory = &H40
        ''' <summary>
        ''' Indicates objects in this directory may be deleted.
        ''' </summary>
        ''' <remarks>
        ''' The "p" permission applies to directory types, and indicates that
        ''' objects in the directory may be deleted, or (stretching naming a
        ''' little) that the directory may be purged.  Note: it does not indicate
        ''' that the RMD command may be used to remove the directory named
        ''' itself, the "d" permission indicator indicates that.
        ''' </remarks>
        CanDeleteDirectory = &H80
        ''' <summary>
        ''' Indicates files in this directory may be retrieved.
        ''' </summary>
        ''' <remarks>
        ''' The "r" permission applies to type=file objects, and for some
        ''' systems, perhaps to other types of objects, and indicates that the
        ''' RETR command may be applied to that object.
        ''' </remarks>
        CanRetrieveFile = &H100
        ''' <summary>
        ''' Indicates files in this directory may be stored.
        ''' </summary>
        ''' <remarks>
        ''' The "w" permission applies to type=file objects, and for some
        ''' systems, perhaps to other types of objects, and indicates that the
        ''' STOR command may be applied to the object named.
        ''' Note: That a permission indicator is set can never imply that the
        ''' appropriate command is guaranteed to work
        ''' </remarks>
        CanStoreFile = &H200
    End Enum

    ''' <summary>
    ''' FTP MLSx item class.
    ''' </summary>
    Public Class FtpMlsxItem
        Inherits FtpItem

        ' RFC defined MLSx object facts
        Private _created As System.Nullable(Of DateTime)
        ' create=
        Private _uniqueId As String
        ' unique=
        Private _permissions As MlsxPerm
        ' perm=
        Private _language As String
        ' lang=
        Private _mediaType As String
        ' media-type=
        Private _characterSet As String
        ' charset=
        ' UNIX specific MLSx object facts
        Private _group As System.Nullable(Of Int32)
        ' UNIX.group=
        Private _owner As System.Nullable(Of Int32)
        ' UNIX.owner=
        ''' <summary>
        ''' Default constructor.
        ''' </summary>
        Public Sub New()
        End Sub


        ''' <summary>
        ''' Constructor to create a new ftp item.
        ''' </summary>
        ''' <param name="name">Name of the item.</param>
        ''' <param name="modified">Modified date and/or time of the item.</param>
        ''' <param name="size">Number of bytes or size of the item.</param>
        ''' <param name="itemType">Type of the item.</param>
        ''' <param name="attributes">UNIX style attributes value.</param>
        ''' <param name="mode">UNIX style mode value</param>
        ''' <param name="rawText">The raw text of the item.</param>
        ''' <param name="created">Created date.</param>
        ''' <param name="uniqueId">Unique identifier.</param>
        ''' <param name="permissions">File action permissions.</param>
        ''' <param name="language">File language.</param>
        ''' <param name="mediaType">MIME file type.</param>
        ''' <param name="characterSet">Character set of the file.</param>
        ''' <param name="group">UNIX style group value.</param>
        ''' <param name="owner">UNIX style owner value.</param>
        Public Sub New(name As String, modified As System.Nullable(Of DateTime), size As Long, itemType As FtpItemType, attributes As String, mode As System.Nullable(Of Int32), _
            rawText As String, created As System.Nullable(Of DateTime), uniqueId As String, permissions As MlsxPerm, language As String, mediaType As String, _
            characterSet As String, group As System.Nullable(Of Int32), owner As System.Nullable(Of Int32))
            MyBase.New(name, modified, size, itemType, attributes, mode, _
                [String].Empty, rawText)
            _created = created
            _uniqueId = uniqueId
            _permissions = permissions
            _language = language
            _mediaType = mediaType
            _characterSet = characterSet
            _group = group
            _owner = owner
        End Sub


        ''' <summary>
        ''' Gets the creation date and time.  Adjusted to from UTC (GMT) to local time.
        ''' </summary>
        Public ReadOnly Property Created() As System.Nullable(Of DateTime)
            Get
                Return _created
            End Get
        End Property


        ''' <summary>
        ''' Gets the unique id of the file or directory.
        ''' </summary>
        Public ReadOnly Property UniqueId() As String
            Get
                Return _uniqueId
            End Get
        End Property

        ''' <summary>
        ''' Gets the enumerated file permissions allowed for the currently logged in user.
        ''' </summary>
        ''' <remarks>
        ''' Permissions are based on FTP server implementation and are represented as
        ''' a flag based enumeration.
        ''' </remarks>
        Public ReadOnly Property Permissions() As MlsxPerm
            Get
                Return _permissions
            End Get
        End Property

        ''' <summary>
        ''' Gets the language of the file per the IANA registry.
        ''' </summary>
        Public ReadOnly Property Language() As String
            Get
                Return _language
            End Get
        End Property

        ''' <summary>
        ''' Gets MIME media-type of teh file contents per the IANA registry.
        ''' </summary>
        Public ReadOnly Property MediaType() As String
            Get
                Return _mediaType
            End Get
        End Property

        ''' <summary>
        ''' Gets the character set per the IANA registry if not UTF-8.
        ''' </summary>
        Public ReadOnly Property CharacterSet() As String
            Get
                Return _characterSet
            End Get
        End Property

        ''' <summary>
        ''' Gets the UNIX specific extension Group integer value for the item.  
        ''' </summary>
        ''' <remarks>
        ''' The UNIX.group fact extension value is not defined by RFC documents and are
        ''' implemented by convention only.  Not all FTP servers will provide the 
        ''' UNIX.* facts.  This value is a nullable field and will be null if no
        ''' fact name was found.
        ''' </remarks>
        Public ReadOnly Property Group() As System.Nullable(Of Int32)
            Get
                Return _group
            End Get
        End Property

        ''' <summary>
        ''' Gets the UNIX specific extension Owner integer value for the item.
        ''' </summary>
        ''' <remarks>
        ''' The UNIX.owner fact extension value is not defined by RFC documents and are
        ''' implemented by convention only.  Not all FTP servers will provide the 
        ''' UNIX.* facts.  This value is a nullable field and will be null if no
        ''' fact name was found.
        ''' </remarks>
        Public ReadOnly Property Owner() As System.Nullable(Of Int32)
            Get
                Return _owner
            End Get
        End Property

        ''' <summary>
        ''' Creates a clone of the item object.
        ''' </summary>
        ''' <return>return a FtpMlsxItem clone.</return>
        Public Overrides Function Clone() As FtpItem
            Dim c As New FtpMlsxItem(MyBase.Name, MyBase.Modified, MyBase.Size, MyBase.ItemType, MyBase.Attributes, MyBase.Mode, _
                MyBase.RawText, _created, _uniqueId, _permissions, _language, _mediaType, _
                _characterSet, _group, _owner)
            Return c
        End Function

        ''' <summary>
        ''' Get the string representation of the FtpMlsxItem.
        ''' </summary>
        ''' <return>String containing FtpMlsxItem information.</return>
        Public Overrides Function ToString() As String
            Dim b As New StringBuilder()
            ' get the base object ToString()
            b.Append(MyBase.ToString())

            ' create the sub-class object ToString()
            If _created IsNot Nothing Then
                b.AppendFormat("Created={0}" & vbCr & vbLf, _created)
            Else
                b.Append("Created=null" & vbCr & vbLf)
            End If
            b.AppendFormat("UniqueId={0}" & vbCr & vbLf, _uniqueId)
            b.AppendFormat("Permissions={0}" & vbCr & vbLf, _permissions)
            b.AppendFormat("Language={0}" & vbCr & vbLf, _language)
            b.AppendFormat("MediaType={0}" & vbCr & vbLf, _mediaType)
            b.AppendFormat("CharacterSet={0}" & vbCr & vbLf, _characterSet)
            If _group IsNot Nothing Then
                b.AppendFormat("Group={0}" & vbCr & vbLf, _group)
            Else
                b.Append("Group=null" & vbCr & vbLf)
            End If
            If _owner IsNot Nothing Then
                b.AppendFormat("Owner={0}" & vbCr & vbLf, _owner)
            Else
                b.Append("Owner=null" & vbCr & vbLf)
            End If
            Return b.ToString()
        End Function
    End Class
End Namespace
